﻿////////////////////////////////////////////////////////////////////////////////////////////////////
// file:	Program.cs
//
// summary:	Implements the program class
////////////////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.Serialization.Json;
using System.Runtime.Serialization;
using System.Diagnostics;

namespace javasigparse
{
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary>   A server json. </summary>
    ///
    /// <remarks>   Wangyanqing, 2016/5/13. </remarks>
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    [DataContract]
    public class ServerJson
    {
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Gets or sets the IP. </summary>
        ///
        /// <value> The IP. </value>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        [DataMember(Order = 0, IsRequired = true)]
        public string ip { get; set; }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Gets or sets the port. </summary>
        ///
        /// <value> The port. </value>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        [DataMember(Order = 1)]
        public int port { get; set; }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary>   Information about the java method. </summary>
    ///
    /// <remarks>   Wangyanqing, 2016/5/13. </remarks>
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    struct JavaMethodInfo
    {
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Constructor. </summary>
        ///
        /// <remarks>   Wangyanqing, 2016/5/13. </remarks>
        ///
        /// <param name="mname">    The mname. </param>
        /// <param name="mtname">   The mtname. </param>
        /// <param name="rettype">  The rettype. </param>
        /// <param name="mline">    The mline. </param>
        /// <param name="ata">      The ata. </param>
        /// <param name="ana">      The ana. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        public JavaMethodInfo(string umname, string mname, string mtname, string rettype, string mline, string[] ata, string[] ana, string[] csata)
        {
            upperstartmethodname = umname;
            methodname = mname;
            methodtypename = mtname;
            returntype = rettype;
            methodline = mline;
            argstypearray = ata;
            argsnamearray = ana;
            csargstypearray = csata;
        }

        /// <summary>   The methodname. </summary>
        public string upperstartmethodname;
        /// <summary>   The methodname. </summary>
        public string methodname;
        /// <summary>   The methodtypename. </summary>
        public string methodtypename;
        /// <summary>   The returntype. </summary>
        public string returntype;
        /// <summary>   The methodline. </summary>
        public string methodline;
        /// <summary>   The argstypearray. </summary>
        public string[] argstypearray;
        /// <summary>   The argsnamearray. </summary>
        public string[] argsnamearray;
        public string[] csargstypearray;
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////////
    /// <summary>   A program. </summary>
    ///
    /// <remarks>   Wangyanqing, 2016/5/13. </remarks>
    ////////////////////////////////////////////////////////////////////////////////////////////////////

    class Program
    {
        public class CMD
        {
            System.Diagnostics.Process _process;
            public CMD()
            {
//                 _process = new System.Diagnostics.Process();
//                 _process.StartInfo.FileName = "cmd.exe";
//                 _process.StartInfo.UseShellExecute = false;
//                 _process.StartInfo.CreateNoWindow = true;
//                 _process.StartInfo.RedirectStandardOutput = true;
//                 _process.StartInfo.RedirectStandardInput = true;
//                 _process.StandardInput.AutoFlush = true;
                //_process.Start();
            }

            public bool Start()
            {
                _process = new System.Diagnostics.Process();
                _process.StartInfo.FileName = "cmd.exe";
                _process.StartInfo.UseShellExecute = false;
                _process.StartInfo.CreateNoWindow = true;
                _process.StartInfo.RedirectStandardOutput = true;
                _process.StartInfo.RedirectStandardInput = true;
                _process.OutputDataReceived += Print;
                bool ret = _process.Start();
                _process.BeginOutputReadLine();
                return ret;
            }

            public void Exit()
            {
                if (_process != null)
                {
                    _process.StandardInput.WriteLine("exit");
                    //_process.StandardInput.WriteLine("exit");
                    //_process.StandardInput.AutoFlush = true;
                    _process.WaitForExit();
                    _process.Dispose();
                    _process.Close();
                    _process = null;
                }
            }

            public void Exec(string cmd)
            {
                if (_process != null)
                {
                    _process.StandardInput.WriteLine(cmd);
                    _process.StandardInput.AutoFlush = true;
                }
            }

            public void Print(object sender, DataReceivedEventArgs e)
            {
                if (_process != null && e.Data != null)
                {
                    System.Diagnostics.Debug.WriteLine(e.Data);
                    //_process.BeginOutputReadLine();
                    //StreamReader reader = _process.StandardOutput;//截取输出流
                    //string output = reader.ReadLine();//每次读取一行
                    //while (!reader.EndOfStream)
                    //{
                    //    //PrintThrendInfo(output);
                    //    //string output = reader.ReadLine();//每次读取一行
                    //    System.Diagnostics.Debug.WriteLine(output);
                    //    output = reader.ReadLine();
                    //}
                    //System.Diagnostics.Debug.WriteLine(reader.ReadToEndAsync());
                    //_process.CancelOutputRead();
                }
            }
        }

        static public string GetCurrentWorkingDirectory()
        {
            return System.IO.Directory.GetCurrentDirectory();
        }

        static public string GetUpperStartString(string str)
        {
            string tmpstr = "" + str[0];
            string upperstartmethodname = tmpstr.ToUpper() + str.Substring(1, str.Length - 1);

            return upperstartmethodname;
        }

        static Dictionary<string, string> argTypeDict = new Dictionary<string, string>
            {
                {"String", "string"},
                {"boolean", "bool"},
            };

        static Dictionary<string, string> argJValueDict = new Dictionary<string, string>
            {
                {"long", "j"},
                {"String", "l"},
                {"boolean", "z"},
                {"int", "i"},
                {"float", "f"},
                {"short", "s"},
            };

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Main entry-point for this application. </summary>
        ///
        /// <remarks>   Wangyanqing, 2016/5/13. </remarks>
        ///
        /// <param name="args"> Array of command-line argument strings. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        static void Main(string[] args)
        {
            string serverListJson = "{ \"servers\": [ { \"ip\" : \"222.73.243.173\", \"port\": 11660 }, { \"ip\" : \"222.73.243.173\", \"port\": 16601 }, { \"ip\" : \"222.73.243.133\", \"port\": 26600 }, { \"ip\" : \"222.73.243.133\", \"port\": 26601 } ] } ";
            serverListJson = serverListJson.Substring(serverListJson.IndexOf('['), serverListJson.IndexOf(']') - serverListJson.IndexOf('[') + 1);// "[{ \"ip\" : \"222.73.243.173\", \"port\": 11660 }, { \"ip\" : \"222.73.243.173\", \"port\": 11660 }]";

            var ms = new MemoryStream(Encoding.UTF8.GetBytes(serverListJson));
            ServerJson[] jsonser = (ServerJson[])new DataContractJsonSerializer(typeof(ServerJson[])).ReadObject(ms);

            int isize = sizeof(int);
            int lsize = sizeof(long);
            int llsize = sizeof(ulong);

            string jarfile = @"E:\Project\GCloudSDK\GCloudSDK_Android\GCloudSDKDemo\libs\GCloudSDK.jar";// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\VoiceChat_Android.jar";
            //string classname = "com/giant/sdk/gcloud/GCloud";// "com/youan/voicechat/vcinterface/VoiceChatInterface";
            string classname = "com/giant/sdk/gcloud/voice/GVoice";// "com/youan/voicechat/vcinterface/VoiceChatInterface";
            string javafilename = Path.GetFileNameWithoutExtension(classname);
            string deasmjavafile = javafilename + ".java";// "VoiceChatInterface.java";
            string sigfile = javafilename + "sig.txt";
//             string jardecompresscmd = "jar xvf " + jarfile;
//             string deassemblecmd = "jad -o -s .java " + classname;
//             string classsigcmd = "javap -s " + classname + " > sig.txt";
            string curdiroutput = GetCurrentWorkingDirectory() + "/output/";
            string curdirtmp = GetCurrentWorkingDirectory() + "/tmp/";
            
            if (!Directory.Exists(curdiroutput))
            {
                Directory.CreateDirectory(curdiroutput);
            }

            if (!Directory.Exists(curdirtmp))
            {
                Directory.CreateDirectory(curdirtmp);
            }

            DeAsmJarFile(jarfile, classname, curdirtmp + deasmjavafile, curdirtmp + sigfile);

//             CMD cmd = new CMD();
//             cmd.Start();
//             cmd.Exec("cd tmp");
//             cmd.Exec(jardecompresscmd);
//             cmd.Exec(deassemblecmd);
//             cmd.Exec(classsigcmd);
//             cmd.Exec("cd ..");
//             cmd.Exit();

            string tmpjavafile = curdirtmp + deasmjavafile;
            string tmpsigfile = curdirtmp + sigfile;
            
            Dictionary<string, JavaMethodInfo> javaMethodDict = ParseMethodInfo(tmpjavafile);

            ParseJavaMethod(tmpjavafile, tmpsigfile, curdiroutput);

            return;

            StreamReader sr = new StreamReader(tmpsigfile);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1.txt", Encoding.Default);
            int maxThreadNum, portThreadNum;
            int minThreadNum;
            ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);
            ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);

            string line;
            char[] separator_space = {' '};
            char[] separator_bracket = { '(' };
            bool isGetMethod = false;
            string strArrayData = "static List<JavaMethodInfo> _methodInfoList = new List<JavaMethodInfo>(){\r\n";
            string strMethodNameArray = "{\r\n";
            string strMethodArray = "";
            string strMethodOnlyArray = "";

            string ioscmethoddefine = "";
            string ioscmethod = "";
            string ioscdllimport = "";

            ioscmethoddefine += "# ifndef __VOICECHAT_WRAP_H__";
            ioscmethoddefine += "\r\n";
            ioscmethoddefine += "#define __VOICECHAT_WRAP_H__";
            ioscmethoddefine += "\r\n";
            ioscmethoddefine += "# import <Foundation/Foundation.h>";
            ioscmethoddefine += "\r\n";
            ioscmethoddefine += "extern \"C\"";
            ioscmethoddefine += "\r\n";
            ioscmethoddefine += "{";
            ioscmethoddefine += "\r\n";

            ioscmethod += "#import \"voiceChat.h\"\r\n";
            ioscmethod += "extern \"C\"";
            ioscmethod += "\r\n";
            ioscmethod += "{";
            ioscmethod += "\r\n";

            ioscdllimport += "#if (UNITY_IOS || UNITY_IPHONE)\r\n";

            string[] spacetarray = new string[] {"Return_Type", "Method_Name" };

            while ((line = sr.ReadLine()) != null)
            {
                if (line == "")
                    continue;

                if (isGetMethod)
                {
                    string[] spacetarray1 = line.Split(separator_space, StringSplitOptions.RemoveEmptyEntries);
                    strArrayData += "\"" + spacetarray1[spacetarray1.Length - 1] + "\"";
                    strArrayData += "),\r\n";
                    isGetMethod = false;
                }
                else
                {
                    string[] bracketarray = line.Split(separator_bracket, StringSplitOptions.RemoveEmptyEntries);

                    if (bracketarray.Length > 1)
                    {
                        //foreach (String str in bracketarray)
                        //{
                        //    spacetarray = str.Split(separator_space, StringSplitOptions.RemoveEmptyEntries);

                        //    string mtname = "";
                        //    //bool result = javaMethodDict.TryGetValue()

                        //    strArrayData += "\tnew JavaMethodInfo(";
                        //    strArrayData += "\"" + spacetarray[spacetarray.Length - 1] + "\", Method_Enum." + javaMethodDict[spacetarray[spacetarray.Length - 1]];
                        //    strArrayData += ", ";
                        //    strArrayData += "typeof(" + spacetarray[spacetarray.Length - 2] + ")";
                        //    strArrayData += ", ";

                        //    strMethodNameArray += "\t" + javaMethodDict[spacetarray[spacetarray.Length - 1]];
                        //    strMethodNameArray += ",\r\n";
                        //    //Console.WriteLine(str);
                        //    break;
                        //}
                        spacetarray = bracketarray[0].Split(separator_space, StringSplitOptions.RemoveEmptyEntries);
                        if (line[line.Length - 1] == ';' && line[line.Length - 2] == ')')
                        {
                            isGetMethod = true;
                            int startpos = line.IndexOf('(') + 1;
                            int endpos = line.IndexOf(')');
                            int linelength = line.Length;
                            string argstr = line.Substring(startpos, endpos - startpos);
                            string[] argsarray = argstr.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);

                            string methodname = spacetarray[spacetarray.Length - 1];
                            string argcomstr = "";
                            string[] argtypearray = new string[argsarray.Length];
                            string[] argnamearray = new string[argsarray.Length];
                            if (argsarray.Length > 0)
                            {
                                for (int i = 0; i < argsarray.Length; ++i)
                                {
                                    string[] argtype = argsarray[i].Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

                                    string arg;
                                    bool ret = argTypeDict.TryGetValue(argtype[argtype.Length - 1], out arg);

                                    if (!ret)
                                        arg = argtype[argtype.Length - 1];

                                    argtypearray[i] = arg;
                                    argcomstr += "_" + arg;
                                }
                            }
                            string methodtypename = spacetarray[spacetarray.Length - 1] + argcomstr;

                            JavaMethodInfo methodinfo;
                            bool result = javaMethodDict.TryGetValue(methodtypename, out methodinfo);

                            if (!result)
                            {
                                //if can't get the method info , continue. Maybe it is Deprecated.
                                isGetMethod = false;
                                continue;
                            }

                            if (methodinfo.methodname == "getRecognizerStr")
                            {
                                isGetMethod = false;
                                continue;
                            }

                            //foreach (String str in bracketarray)
                            {
                            //spacetarray = str.Split(separator_space, StringSplitOptions.RemoveEmptyEntries);

                            string mtname = "";
                            //bool result = javaMethodDict.TryGetValue()

                            strArrayData += "\tnew JavaMethodInfo(";
                            strArrayData += "\"" + spacetarray[spacetarray.Length - 1] + "\", Method_Enum." + spacetarray[spacetarray.Length - 1] + argcomstr;
                            strArrayData += ", ";
                            strArrayData += "typeof(" + javaMethodDict[methodtypename].returntype + ")";
                            strArrayData += ", ";

                            strMethodNameArray += "\t" + spacetarray[spacetarray.Length - 1] + argcomstr;
                            strMethodNameArray += ",\r\n";
                            //Console.WriteLine(str);
                            // break;
                            }

                            

                            strMethodArray += "/// <summary>";
                            strMethodArray += "\r\n";
                            strMethodArray += "///";
                            strMethodArray += "\r\n";
                            strMethodArray += "/// </summary>";
                            strMethodArray += "\r\n";

                            if (result)
                            {
                                argsarray = methodinfo.argstypearray;
                                argnamearray = methodinfo.argsnamearray;
                                if (argsarray.Length > 0)
                                {
                                    for (int i = 0; i < argsarray.Length; ++i)
                                    {
                                        strMethodArray += "/// <param name=\"" + methodinfo.argsnamearray[i] + "\"></param>";
                                        strMethodArray += "\r\n";
                                    }
                                }
                            }
                            else
                            {
                                if (argsarray.Length > 0)
                                {
                                    for (int i = 0; i < argsarray.Length; ++i)
                                    {
                                        strMethodArray += "/// <param name=\"arg" + i + "\"></param>";
                                        strMethodArray += "\r\n";
                                    }
                                }
                            }

                            if (spacetarray[spacetarray.Length - 2] != "void")
                            {
                                strMethodArray += "/// <returns></returns>";
                                strMethodArray += "\r\n";
                            }

                            if (result)
                            {
                                strMethodArray += methodinfo.methodline;
                                strMethodOnlyArray += methodinfo.methodline;
                            }
                            else
                            {
                                //strMethodArray += line.Substring(0, line.Length - 1);
                                strMethodArray += line.Substring(0, line.IndexOf('(') + 1);

                                if (argsarray.Length > 0)
                                {
                                    int i = 0;
                                    string argtype = "";
                                    result = argTypeDict.TryGetValue(argsarray[i], out argtype);

                                    if (result)
                                        strMethodArray += argtype + " arg0";
                                    else
                                        strMethodArray += argsarray[0] + " arg0";
                                    for (i = 1; i < argsarray.Length; ++i)
                                    {
                                        argtype = "";
                                        result = argTypeDict.TryGetValue(argsarray[i], out argtype);

                                        if (result)
                                            strMethodArray += ", " + argtype + " arg" + i;
                                        else
                                            strMethodArray += ", " + argsarray[i] + " arg" + i;
                                    }
                                }

                                strMethodArray += ")";
                            }

                            strMethodOnlyArray += "\r\n{\r\n";
                            strMethodArray += "\r\n{\r\n";

                            strMethodArray += "#if UNITY_ANDROID\r\n";

                            strMethodArray += "JniStaticMethod jniMethod;";
                            strMethodArray += "\r\n";
                            strMethodArray += "bool result = _jniMethodDict.TryGetValue(Method_Enum." + spacetarray[spacetarray.Length - 1] + argcomstr + ", out jniMethod);";
                            strMethodArray += "\r\n";
                            strMethodArray += "if (result)";
                            strMethodArray += "\r\n";
                            strMethodArray += "{";
                            strMethodArray += "\r\n";
                            //strMethodArray += "int jniret = AndroidJNI.AttachCurrentThread();";
                            //strMethodArray += "\r\n";
                            //strMethodArray += "if(jniret != 0)";
                            //strMethodArray += "\r\n";
                            //strMethodArray += "{\r\n";
                            //strMethodArray += "Debug.Log(\"AndroidJNI.AttachCurrentThread failed! return code:\" + jniret);";
                            //strMethodArray += "\r\n";
                            //if (methodinfo.returntype != "void")
                            //{
                            //    string argtype = "";
                            //    result = argTypeDict.TryGetValue(methodinfo.returntype, out argtype);

                            //    if (!result)
                            //        argtype = methodinfo.returntype;

                            //    if (argtype == "bool")
                            //        strMethodArray += "return false;";
                            //    else if (argtype == "int" | argtype == "short" || argtype == "char" | argtype == "long")
                            //        strMethodArray += "return 0;";
                            //    else if (argtype == "float")
                            //        strMethodArray += "return 0.0f;";
                            //    else
                            //        strMethodArray += "return (" + argtype + ")null;";
                            //    strMethodArray += "\r\n";
                            //}
                            //else
                            //    strMethodArray += "return;\r\n";
                            //strMethodArray += "}\r\n";
                            strMethodArray += "jvalue[] args = null;";
                            strMethodArray += "\r\n";

                            List<string> needDelRefStringList = new List<string>();
                            if (argsarray.Length > 0)
                            {
                                strMethodArray += "args = new jvalue[" + argsarray.Length + "];";
                                strMethodArray += "\r\n";
                                for (int i = 0; i < argsarray.Length; ++i)
                                {
                                    strMethodArray += "args[" + i + "].";

                                    string argtype = "";
                                    result = argJValueDict.TryGetValue(argsarray[i], out argtype);

                                    if (!result)
                                        argtype = "l";

                                    if (argsarray[i] == "String")
                                    {
                                        needDelRefStringList.Add("args[" + i + "]." + argtype);
                                        strMethodArray += argtype + " = AndroidJNI.NewStringUTF(" + argnamearray[i] + ");";
                                    }
                                    else if (argsarray[i].Contains("Listener") || argsarray[i].Contains("Listsener"))
                                    {
                                        //needDelRefStringList.Add("args[" + i + "]." + argtype);
                                        strMethodArray += argtype + " = AndroidJNIHelper.CreateJavaProxy(" + argnamearray[i] +  ");";
                                    }
                                    else
                                        strMethodArray += argtype + " = " + argnamearray[i] + ";";
                                    strMethodArray += "\r\n";
                                }
                                strMethodArray += "\r\n";
                                //strMethodArray += "args[0].l = _activityContext.GetRawClass();";
                                //strMethodArray += " args[1].i = GID;";
                                //strMethodArray += "args[2].i = ZID;";
                                //strMethodArray += "rgs[3].i = UID;";
                                //strMethodArray += "args[4].l = AndroidJNI.NewStringUTF(clientName);";
                                //strMethodArray += "args[5].l = AndroidJNI.NewStringUTF(clientVer);";
                            }
                            else
                            {
                                strMethodArray += "args = new jvalue[1];";
                                strMethodArray += "\r\n";
                                strMethodArray += "\r\n";
                            }

                            if (methodinfo.returntype != "void")
                            {
                                string argtype = "";
                                result = argTypeDict.TryGetValue(methodinfo.returntype, out argtype);

                                if (!result)
                                    argtype = methodinfo.returntype;

                                strMethodArray += argtype + " retObj = (" + argtype + ")jniMethod.Call(args);";
                                strMethodArray += "\r\n";

                                for (int i = 0; i < needDelRefStringList.Count; ++i)
                                {
                                    strMethodArray += "AndroidJNI.DeleteLocalRef(" + needDelRefStringList[i] + ");";
                                    strMethodArray += "\r\n";
                                }
                                //strMethodArray += "AndroidJNI.DetachCurrentThread();";
                                strMethodArray += "\r\n";
                                strMethodArray += "return retObj;";
                            }
                            else
                            {
                                strMethodArray += "jniMethod.Call(args);";
                                //strMethodArray += "\r\n";
                                //strMethodArray += "AndroidJNI.DetachCurrentThread();";
                                for (int i = 0; i < needDelRefStringList.Count; ++i)
                                {
                                    strMethodArray += "\r\n";
                                    strMethodArray += "AndroidJNI.DeleteLocalRef(" + needDelRefStringList[i] + ");";
                                }
                            }

                            strMethodArray += "\r\n";

                            strMethodArray += "}";
                            strMethodArray += "\r\n";
                            strMethodArray += "else";
                            strMethodArray += "\r\n";
                            strMethodArray += "{";
                            strMethodArray += "\r\n";
                            strMethodArray += "Debug.Log(\"_jniMethodDict get method " + spacetarray[spacetarray.Length - 1] + " failed!\");";
                            strMethodArray += "\r\n";

                            if (methodinfo.returntype != "void")
                            {
                                string argtype = "";
                                result = argTypeDict.TryGetValue(methodinfo.returntype, out argtype);

                                if (!result)
                                    argtype = methodinfo.returntype;

                                if(argtype == "bool")
                                    strMethodArray += "return false;";
                                else if(argtype == "int" | argtype == "short" || argtype == "char" | argtype == "long")
                                    strMethodArray += "return 0;";
                                else if (argtype == "float")
                                    strMethodArray += "return 0.0f;";
                                else
                                    strMethodArray += "return (" + argtype + ")null;";
                                strMethodArray += "\r\n";

                                if (argtype == "bool")
                                    strMethodOnlyArray += "return false;";
                                else if (argtype == "int" | argtype == "short" || argtype == "char" | argtype == "long")
                                    strMethodOnlyArray += "return 0;";
                                else if (argtype == "float")
                                    strMethodOnlyArray += "return 0.0f;";
                                else
                                    strMethodOnlyArray += "return (" + argtype + ")null;";
                            }
                            //strMethodArray += "return false;";
                            strMethodArray += "}";
                            strMethodArray += "\r\n";

                            strMethodArray += "#elif (UNITY_IOS || UNITY_IPHONE)\r\n";
                            //IOS code
                            ioscdllimport += "\r\n[DllImport(\"__Internal\")]\r\n";
                            ioscdllimport += "private static extern " + methodinfo.returntype + " GiantSDK_" + methodinfo.upperstartmethodname + "(";

                            if (methodinfo.argstypearray.Length > 0)
                            {
                                ioscdllimport += methodinfo.csargstypearray[0];

                                ioscdllimport += " " + methodinfo.argsnamearray[0];

                                for (int i = 1; i < methodinfo.csargstypearray.Length; ++i)
                                {
                                    ioscdllimport += ", " + methodinfo.csargstypearray[i];
                                    ioscdllimport += " " + methodinfo.argsnamearray[i];
                                }
                            }

                            ioscdllimport += ")";
                            ioscdllimport += ";\r\n";

                            //c method generation
                            // //define
                            if (methodinfo.returntype == "string")
                                ioscmethoddefine += "extern const char* GiantSDK_" + methodinfo.upperstartmethodname + "(";
                            else
                                ioscmethoddefine += "extern " + methodinfo.returntype + " GiantSDK_" + methodinfo.upperstartmethodname + "(";
                            if (methodinfo.argstypearray.Length > 0)
                            {
                                //int posstart = methodinfo.methodline.IndexOf('(');
                                //ioscmethoddefine += methodinfo.methodline.Substring(posstart, methodinfo.methodline.Length - posstart);
   
                                //ioscmethoddefine += methodinfo.csargstypearray[0];
                                if (methodinfo.csargstypearray[0] == "string")
                                    ioscmethoddefine += "const char*";
                                else if (methodinfo.argstypearray[0].Contains("Listener"))
                                    ioscmethoddefine += methodinfo.csargstypearray[0] + "*";
                                else
                                    ioscmethoddefine += methodinfo.csargstypearray[0];

                                ioscmethoddefine += " " + methodinfo.argsnamearray[0];

                                for (int i = 1; i < methodinfo.csargstypearray.Length; ++i)
                                {
                                    if(methodinfo.csargstypearray[i] == "string")
                                        ioscmethoddefine += ", " + "const char*";
                                    else if(methodinfo.argstypearray[i].Contains("Listener"))
                                        ioscmethoddefine += ", " + methodinfo.csargstypearray[i] + "*";
                                    else
                                        ioscmethoddefine += ", " + methodinfo.csargstypearray[i];

                                    ioscmethoddefine += " " + methodinfo.argsnamearray[i];
                                }
                            }

                            ioscmethoddefine += ")";
                            
                            ioscmethoddefine += ";\r\n";

                            //method body
                            if (methodinfo.returntype == "string")
                                ioscmethod += "extern const char* GiantSDK_" + methodinfo.upperstartmethodname + "(";
                            else
                                ioscmethod += "extern " + methodinfo.returntype + " GiantSDK_" + methodinfo.upperstartmethodname + "(";
                            if (methodinfo.argstypearray.Length > 0)
                            {
                                //int posstart = methodinfo.methodline.IndexOf('(');
                                //ioscmethoddefine += methodinfo.methodline.Substring(posstart, methodinfo.methodline.Length - posstart);

                                //ioscmethoddefine += methodinfo.csargstypearray[0];
                                if (methodinfo.csargstypearray[0] == "string")
                                    ioscmethod += "const char*";
                                else if (methodinfo.argstypearray[0].Contains("Listener"))
                                    ioscmethod += methodinfo.csargstypearray[0] + "*";
                                else
                                    ioscmethod += methodinfo.csargstypearray[0];

                                ioscmethod += " " + methodinfo.argsnamearray[0];

                                for (int i = 1; i < methodinfo.csargstypearray.Length; ++i)
                                {
                                    if (methodinfo.csargstypearray[i] == "string")
                                        ioscmethod += ", " + "const char*";
                                    else if (methodinfo.argstypearray[i].Contains("Listener"))
                                        ioscmethod += ", " + methodinfo.csargstypearray[i] + "*";
                                    else
                                        ioscmethod += ", " + methodinfo.csargstypearray[i];

                                    ioscmethod += " " + methodinfo.argsnamearray[i];
                                }
                            }

                            ioscmethod += ")\r\n";

                            ioscmethod += "{\r\n";

                            ioscmethod += "//TODO:need implement the method, by hand";

                            ioscmethod += "\r\n}\r\n\r\n";

                            //c method generation end

                            if (methodinfo.returntype != "void")
                            {
                                string argtype = "";
                                result = argTypeDict.TryGetValue(methodinfo.returntype, out argtype);

                                if (!result)
                                    argtype = methodinfo.returntype;

                                strMethodArray += argtype + " retObj = (" + argtype + ")GiantSDK_" + methodinfo.upperstartmethodname + "(";

                                if (methodinfo.argsnamearray.Length > 0)
                                {
                                    strMethodArray += methodinfo.argsnamearray[0];
                                    for (int i = 1; i < methodinfo.argsnamearray.Length; ++i)
                                    {
                                        strMethodArray += ", " + methodinfo.argsnamearray[i];
                                    }
                                }
                                strMethodArray += ");";
                                strMethodArray += "\r\n";
                                strMethodArray += "return retObj;";
                                strMethodArray += "\r\n";
                            }
                            else
                            {
                                strMethodArray += "GiantSDK_" + methodinfo.upperstartmethodname + "(";
                                if (methodinfo.argsnamearray.Length > 0)
                                {
                                    strMethodArray += methodinfo.argsnamearray[0];
                                    for (int i = 1; i < methodinfo.argsnamearray.Length; ++i)
                                    {
                                        strMethodArray += ", " + methodinfo.argsnamearray[i];
                                    }
                                }
                                strMethodArray += ");";
                                strMethodArray += "\r\n";
                            }

                            //IOS CODE END
                            strMethodArray += "#endif\r\n";

                            strMethodOnlyArray += "\r\n}\r\n\r\n";
                            strMethodArray += "}\r\n\r\n";
                        }
                    }
                }
                
               // Console.WriteLine(line);
            }
            strArrayData += "};\r\n";
            strMethodNameArray += "}\r\n";

            ioscmethoddefine += "}";
            ioscmethoddefine += "\r\n";
            ioscmethoddefine += "#endif";
            ioscmethoddefine += "\r\n";

            ioscmethod += "}";
            ioscmethod += "\r\n";
            ioscmethod += "#endif";
            ioscmethod += "\r\n";

            ioscdllimport += "#endif";
            ioscdllimport += "\r\n";

            string enumfile = curdiroutput + javafilename + "sig1_output.txt";

            FileStream fs = new FileStream(enumfile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_output.txt", FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            //开始写入
            sw.Write(strArrayData);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();

            string methodnamefile = curdiroutput + javafilename + "sig1_methodname_output.txt";
            fs = new FileStream(methodnamefile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_methodname_output.txt", FileMode.Create);
            sw = new StreamWriter(fs);
            //开始写入
            sw.Write(strMethodNameArray);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();

            string methodfile = curdiroutput + javafilename + "sig1_method_output.txt";
            fs = new FileStream(methodfile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_method_output.txt", FileMode.Create);
            sw = new StreamWriter(fs);
            //开始写入
            sw.Write(strMethodArray);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();

            string methodonlyfile = curdiroutput + javafilename + "sig1_method_only_output.txt";
            fs = new FileStream(methodonlyfile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_method_only_output.txt", FileMode.Create);
            sw = new StreamWriter(fs);
            //开始写入
            sw.Write(strMethodOnlyArray);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();

            string ioscmethoddefinefile = curdiroutput + javafilename + "chatVoice.h";
            fs = new FileStream(ioscmethoddefinefile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_method_only_output.txt", FileMode.Create);
            sw = new StreamWriter(fs);
            //开始写入
            sw.Write(ioscmethoddefine);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();

            string ioscmethodfile = curdiroutput + javafilename + "chatVoice.mm";
            fs = new FileStream(ioscmethodfile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_method_only_output.txt", FileMode.Create);
            sw = new StreamWriter(fs);
            //开始写入
            sw.Write(ioscmethod);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();

            string csdllimportfile = curdiroutput + javafilename + "csdllimport.txt";
            fs = new FileStream(csdllimportfile, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_method_only_output.txt", FileMode.Create);
            sw = new StreamWriter(fs);
            //开始写入
            sw.Write(ioscdllimport);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
        }

        public static void ParseJavaMethod(string javafile, string sigfile, string outputdir)
        {
            Dictionary<string, JavaMethodInfo> javaMethodDict = ParseMethodInfo(javafile);

            StreamReader sr = new StreamReader(sigfile);

            string line;
            char[] separator_space = { ' ' };
            char[] separator_bracket = { '(' };
            bool isGetMethod = false;

            string[] spacetarray = new string[] { "Return_Type", "Method_Name" };

            string strMethodArray = "";
            string strMethodOnlyArray = "";

            string ioscdllimport = "";

            while ((line = sr.ReadLine()) != null)
            {
                if (line == "")
                    continue;

                if (isGetMethod)
                {
                    string[] spacetarray1 = line.Split(separator_space, StringSplitOptions.RemoveEmptyEntries);
                    //strArrayData += "\"" + spacetarray1[spacetarray1.Length - 1] + "\"";
                    //strArrayData += "),\r\n";
                    isGetMethod = false;
                }
                else
                {
                    string[] bracketarray = line.Split(separator_bracket, StringSplitOptions.RemoveEmptyEntries);

                    if (bracketarray.Length > 1)
                    {
                        spacetarray = bracketarray[0].Split(separator_space, StringSplitOptions.RemoveEmptyEntries);
                        if (line[line.Length - 1] == ';' && line[line.Length - 2] == ')')
                        {
                            isGetMethod = true;
                            int startpos = line.IndexOf('(') + 1;
                            int endpos = line.IndexOf(')');
                            int linelength = line.Length;
                            string argstr = line.Substring(startpos, endpos - startpos);
                            string[] argsarray = argstr.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);

                            string methodname = spacetarray[spacetarray.Length - 1];
                            string argcomstr = "";
                            string[] argtypearray = new string[argsarray.Length];
                            string[] argnamearray = new string[argsarray.Length];
                            if (argsarray.Length > 0)
                            {
                                for (int i = 0; i < argsarray.Length; ++i)
                                {
                                    string[] argtypes = argsarray[i].Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

                                    string arg;
                                    bool ret = argTypeDict.TryGetValue(argtypes[argtypes.Length - 1], out arg);

                                    if (!ret)
                                        arg = argtypes[argtypes.Length - 1];

                                    argtypearray[i] = arg;
                                    argcomstr += "_" + arg;
                                }
                            }
                            string methodtypename = spacetarray[spacetarray.Length - 1] + argcomstr;

                            JavaMethodInfo methodinfo;
                            bool result = javaMethodDict.TryGetValue(methodtypename, out methodinfo);

                            if (!result)
                            {
                                //if can't get the method info , continue. Maybe it is Deprecated.
                                isGetMethod = false;
                                continue;
                            }

                            if (methodinfo.methodname == "getRecognizerStr")
                            {
                                isGetMethod = false;
                                continue;
                            }

                            strMethodArray += "/// <summary>";
                            strMethodArray += "\r\n";
                            strMethodArray += "///";
                            strMethodArray += "\r\n";
                            strMethodArray += "/// </summary>";
                            strMethodArray += "\r\n";

                            if (result)
                            {
                                argsarray = methodinfo.argstypearray;
                                argnamearray = methodinfo.argsnamearray;
                                if (argsarray.Length > 0)
                                {
                                    for (int i = 0; i < argsarray.Length; ++i)
                                    {
                                        strMethodArray += "/// <param name=\"" + methodinfo.argsnamearray[i] + "\"></param>";
                                        strMethodArray += "\r\n";
                                    }
                                }
                            }
                            else
                            {
                                if (argsarray.Length > 0)
                                {
                                    for (int i = 0; i < argsarray.Length; ++i)
                                    {
                                        strMethodArray += "/// <param name=\"arg" + i + "\"></param>";
                                        strMethodArray += "\r\n";
                                    }
                                }
                            }

                            if (spacetarray[spacetarray.Length - 2] != "void")
                            {
                                strMethodArray += "/// <returns></returns>";
                                strMethodArray += "\r\n";
                            }

                            if (result)
                            {
                                strMethodArray += methodinfo.methodline;
                                strMethodOnlyArray += methodinfo.methodline;
                            }
                            else
                            {
                                //strMethodArray += line.Substring(0, line.Length - 1);
                                strMethodArray += line.Substring(0, line.IndexOf('(') + 1);

                                if (argsarray.Length > 0)
                                {
                                    int i = 0;
                                    string argtypea = "";
                                    result = argTypeDict.TryGetValue(argsarray[i], out argtypea);

                                    if (result)
                                        strMethodArray += argtypea + " arg0";
                                    else
                                        strMethodArray += argsarray[0] + " arg0";
                                    for (i = 1; i < argsarray.Length; ++i)
                                    {
                                        argtypea = "";
                                        result = argTypeDict.TryGetValue(argsarray[i], out argtypea);

                                        if (result)
                                            strMethodArray += ", " + argtypea + " arg" + i;
                                        else
                                            strMethodArray += ", " + argsarray[i] + " arg" + i;
                                    }
                                }

                                strMethodArray += ")";
                            }

                            strMethodOnlyArray += "\r\n{\r\n";
                            strMethodArray += "\r\n{\r\n";

                            strMethodArray += "#if UNITY_ANDROID\r\n";

                            if (methodinfo.returntype != "void")
                            {
                                string argtype = "";
                                result = argTypeDict.TryGetValue(methodinfo.returntype, out argtype);

                                if (!result)
                                    argtype = methodinfo.returntype;;

                                //strMethodArray += "return ";
                                strMethodArray += "return gCloudJavaObject.Call<" + argtype + ">(\"" + methodinfo.methodname + "\"";
                            }
                            else
                                strMethodArray += "gCloudJavaObject.Call(\"" + methodinfo.methodname + "\"";

                            if (argsarray.Length > 0)
                            {
                                for (int i = 0; i < methodinfo.argsnamearray.Length; ++i)
                                {
                                    strMethodArray += ", " + methodinfo.argsnamearray[i];
                                }
                            }

                            strMethodArray += ");";

                            strMethodArray += "\r\n";
                            strMethodArray += "#elif (UNITY_IOS || UNITY_IPHONE)\r\n";

                            ioscdllimport += "\r\n[DllImport(\"__Internal\")]\r\n";
                            ioscdllimport += "private static extern " + methodinfo.returntype + " GCloud_" + methodinfo.upperstartmethodname + "(";

                            if (methodinfo.argstypearray.Length > 0)
                            {
                                ioscdllimport += methodinfo.csargstypearray[0];

                                ioscdllimport += " " + methodinfo.argsnamearray[0];

                                for (int i = 1; i < methodinfo.csargstypearray.Length; ++i)
                                {
                                    ioscdllimport += ", " + methodinfo.csargstypearray[i];
                                    ioscdllimport += " " + methodinfo.argsnamearray[i];
                                }
                            }

                            ioscdllimport += ")";
                            ioscdllimport += ";\r\n";

                            if (methodinfo.returntype != "void")
                            {
                                string argtype = "";
                                result = argTypeDict.TryGetValue(methodinfo.returntype, out argtype);

                                if (!result)
                                    argtype = methodinfo.returntype;

                                strMethodArray += "return GCloud_" + methodinfo.methodname + "(";
                            }
                            else
                            {
                                strMethodArray += "GCloud_" + methodinfo.methodname + "(";
                            }

                            if (argsarray.Length > 0)
                            {
                                strMethodArray += methodinfo.argsnamearray[0];
                                for (int i = 1; i < methodinfo.argsnamearray.Length; ++i)
                                {
                                    strMethodArray += ", " + methodinfo.argsnamearray[i];
                                }
                            }

                            strMethodArray += ");";

                            strMethodArray += "\r\n";

                            strMethodArray += "#else\r\n";
                            if (methodinfo.returntype != "void")
                            {
                                string argtypeelse = "";
                                result = argTypeDict.TryGetValue(methodinfo.returntype, out argtypeelse);

                                if (!result)
                                    argtypeelse = methodinfo.returntype;

                                if (argtypeelse == "bool")
                                    strMethodArray += "return false;";
                                else if (argtypeelse == "int" | argtypeelse == "short" || argtypeelse == "char" | argtypeelse == "long")
                                    strMethodArray += "return 0;";
                                else if (argtypeelse == "float")
                                    strMethodArray += "return 0.0f;";
                                else
                                    strMethodArray += "return (" + argtypeelse + ")null;";
                                strMethodArray += "\r\n";
                            }
//                             if (argtype == "bool")
//                                 strMethodOnlyArray += "return false;";
//                             else if (argtype == "int" | argtype == "short" || argtype == "char" | argtype == "long")
//                                 strMethodOnlyArray += "return 0;";
//                             else if (argtype == "float")
//                                 strMethodOnlyArray += "return 0.0f;";
//                             else
//                                 strMethodOnlyArray += "return (" + argtype + ")null;";

                            strMethodArray += "#endif\r\n";

                            strMethodArray += "}";

                            strMethodArray += "\r\n\r\n";
                        }
                    }
                }
            }

            string methodnamefile = outputdir + Path.GetFileNameWithoutExtension(javafile) + "_method_output.txt";
            SaveFile(methodnamefile, strMethodArray);

            SaveFile(outputdir + Path.GetFileNameWithoutExtension(javafile) + "_ios_dllimport", ioscdllimport);
        }

        public static void SaveFile(string filename, string data)
        {
            FileStream fs = new FileStream(filename, FileMode.Create);// @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\sig1_methodname_output.txt", FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            //开始写入
            sw.Write(data);
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
        }

        public static void DeAsmJarFile(string jarfile, string classname, string javafile, string sigfile)
        {
            //string sigfile = "sig.txt";
            //string deasmjavafile = "VoiceChatInterface.java";
            //string jarfile = @"E:\Project\VoiceNew\trunk\SDK\ProjectsSDK\公用\Android\VoiceChat_Android.jar";
            //string classname = "com/youan/voicechat/vcinterface/VoiceChatInterface";
            string jardecompresscmd = "jar xvf \"" + jarfile + "\"";
            string deassemblecmd = "jad -o -s .java " + classname;
            string classsigcmd = "javap -s " + classname + " > \"" + sigfile + "\"";
            string olddir = GetCurrentWorkingDirectory();
            string curjavadir = Path.GetDirectoryName(javafile);
            string cursigdir = Path.GetDirectoryName(sigfile);

            if (!Directory.Exists(curjavadir))
            {
                Directory.CreateDirectory(curjavadir);
            }
            if (!Directory.Exists(cursigdir))
            {
                Directory.CreateDirectory(cursigdir);
            }

            CMD cmd = new CMD();
            cmd.Start();
            cmd.Exec("cd \"" + curjavadir + "\"");
            cmd.Exec(jardecompresscmd);
            cmd.Exec(deassemblecmd);
            //cmd.Exec("cd " + cursigdir);
            cmd.Exec(classsigcmd);
            cmd.Exec("cd \"" + olddir + "\"");
            cmd.Exit();
        }

        public static Dictionary<string, JavaMethodInfo> ParseMethodInfo(string javafile)
        {
            Dictionary<string, JavaMethodInfo> javaMethodDict = new Dictionary<string, JavaMethodInfo>();
            //string javafile = file;// @"C:\Users\wangyanqing\StudioProjects\VoiceChat\app\src\main\java\com\youan\voicechat\vcinterface\VoiceChatInterface.java";
            
            StreamReader javasr = new StreamReader(javafile, Encoding.Default);
            string javasrline;
            bool isDeprecated = false;
            while ((javasrline = javasr.ReadLine()) != null)
            {
                if (javasrline.Contains("@Deprecated") || javasrline.Contains("@deprecated"))
                {
                    isDeprecated = true;
                    continue;
                }

                javasrline = javasrline.Replace("final ", "");
                if (javasrline.Contains("public") && javasrline.Contains("(") && javasrline.Contains(")") && javasrline[javasrline.Length - 1] != ';')
                {
                    if (isDeprecated)
                    {
                        isDeprecated = false;
                        continue;
                    }

                    string methodstr = javasrline.Substring(0, javasrline.IndexOf('('));
                    string[] methodstrarray = methodstr.Split(new char[] { ' ' });
                    string methodname = methodstrarray[methodstrarray.Length - 1];
                    string returntype = methodstrarray[methodstrarray.Length - 2];

                    string upperstartmethodname = GetUpperStartString(methodname);

                    string argstr = javasrline.Substring(javasrline.IndexOf('(') + 1, javasrline.IndexOf(')') - javasrline.IndexOf('(') - 1);
                    string[] argstrarray = argstr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    string argcomstr = "";
                    string[] typeargarray = new string[argstrarray.Length];
                    string[] nameargarray = new string[argstrarray.Length];
                    for (int i = 0; i < argstrarray.Length; ++i)
                    {
                        string[] argtypename = argstrarray[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        argcomstr += "_" + argtypename[0];
                        typeargarray[i] = argtypename[0];
                        nameargarray[i] = argtypename[1];
                    }

                    javasrline = javasrline.Replace(" String ", " string ");
                    javasrline = javasrline.Replace(",String ", ",string ");
                    javasrline = javasrline.Replace("(String ", "(string ");
                    javasrline = javasrline.Replace(" boolean ", " bool ");
                    javasrline = javasrline.Replace(",boolean ", ",bool ");
                    javasrline = javasrline.Replace("(boolean ", "(bool ");

                    argstr = javasrline.Substring(javasrline.IndexOf('(') + 1, javasrline.IndexOf(')') - javasrline.IndexOf('(') - 1);
                    argstrarray = argstr.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                    argcomstr = "";
                    string[] cstypeargarray = new string[argstrarray.Length];
                    for (int i = 0; i < argstrarray.Length; ++i)
                    {
                        string[] argtypename = argstrarray[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        argcomstr += "_" + argtypename[0];
                        cstypeargarray[i] = argtypename[0];
                    }

                    string rettype;
                    bool result = argTypeDict.TryGetValue(returntype, out rettype);

                    if (!result)
                        rettype = returntype;

                    JavaMethodInfo methodinfo = new JavaMethodInfo(upperstartmethodname, methodname, methodname + argcomstr, rettype, javasrline.Substring(0, javasrline.IndexOf(')') + 1), typeargarray, nameargarray, cstypeargarray);

                    JavaMethodInfo outmethodinfo;
                    result = javaMethodDict.TryGetValue(methodname + argcomstr, out outmethodinfo);

                    if (!result)
                        javaMethodDict.Add(methodname + argcomstr, methodinfo);
                }
               
            }

            return javaMethodDict;
        }
    }
}
